package utils

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"dump/config"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

type Notification struct {
	Title   string `json:"title"`
	Message string `json:"message"`
	Status  string `json:"status"` // 例如："success", "failure", "warning"
}

func SendNotification(webhookURL, secret, Prompt, title, message, status string) error {
	if webhookURL == "" {
		return fmt.Errorf("webhook URL is empty")
	}

	// 如果有secret，生成带签名的URL
	finalURL := webhookURL
	if secret != "" {
		timestamp := time.Now().UnixNano() / 1e6
		sign, err := generateSign(secret, timestamp)
		if err != nil {
			return err
		}

		u, err := url.Parse(webhookURL)
		if err != nil {
			return err
		}

		q := u.Query()
		q.Set("timestamp", strconv.FormatInt(timestamp, 10))
		q.Set("sign", sign)
		u.RawQuery = q.Encode()
		finalURL = u.String()
	}

	// 构建通知内容
	content := fmt.Sprintf("## %s\n- **状态**: %s\n- **信息**: %s\n- **详情**: %s", title, status, Prompt, message)

	// 构造钉钉请求体
	payload := map[string]interface{}{
		"msgtype": "markdown",
		"markdown": map[string]string{
			"title": title,
			"text":  content,
		},
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return err
	}

	// 发送HTTP请求
	resp, err := http.Post(finalURL, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("钉钉通知发送失败，状态码: %d", resp.StatusCode)
	}

	return nil
}

// SendNotificationWithConfig 带有配置控制的钉钉通知发送
func SendNotificationWithConfig(cfg config.MySQLConfig, title, message, status string) error {
	// 检查通知是否启用 false
	if !cfg.NotifyEnable {
		return nil
	}

	// 检查通知条件 NotifyAll=false 不发送成功
	if status == "success" && !cfg.NotifyAll {
		return nil
	}

	// 发送实际通知
	return SendNotification(cfg.WebhookURL, cfg.Secret, cfg.Prompt, title, message, status)
}

func generateSign(secret string, timestamp int64) (string, error) {
	signStr := fmt.Sprintf("%d\n%s", timestamp, secret)
	h := hmac.New(sha256.New, []byte(secret))
	h.Write([]byte(signStr))
	return url.QueryEscape(base64.StdEncoding.EncodeToString(h.Sum(nil))), nil
}
